package com.jigoucai.module;

import com.jigoucai.bean.dict.Dict;
import com.jigoucai.bean.param.req.payment.RequestPaymentReq;
import com.jigoucai.bean.param.resp.BaseResp;
import com.jigoucai.entity.finance.Current;
import com.jigoucai.entity.user.Account;
import com.jigoucai.util.Code;
import com.jigoucai.util.JgcUtil;
import org.nutz.dao.Cnd;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.Times;
import org.nutz.lang.random.R;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.Mvcs;
import org.nutz.mvc.adaptor.JsonAdaptor;
import org.nutz.mvc.adaptor.XmlAdaptor;
import org.nutz.mvc.annotation.*;
import org.nutz.weixin.bean.mp.biz.WXMsgData;
import org.nutz.weixin.bean.mp.req.MessageWxopenTemplateSendReq;
import org.nutz.weixin.bean.pay.biz.RequestPayment;
import org.nutz.weixin.bean.pay.req.UnifiedorderReq;
import org.nutz.weixin.bean.pay.resp.UnifiedorderResp;
import org.nutz.weixin.util.Util;
import org.nutz.weixin.util.mp.MpUtil;
import org.nutz.weixin.util.pay.PayUtil;

/**
 * Created by Jianghao on 2018/3/24
 *
 * @author Jianghao(howechiang @ gmail.com)
 */
@IocBean
@Fail("http:500")
@At("/payment")
public class PaymentModule extends BaseModule {

    @Inject("java:$conf.get('weixin.miniapp.appid')")
    protected String WEIXIN_MINIAPP_APPID;
    @Inject("java:$conf.get('weixin.miniapp.appsecret')")
    protected String WEIXIN_MINIAPP_APPSECRET;
    @Inject("java:$conf.get('weixin.payment.mchid')")
    protected String WEIXIN_PAYMENT_MCHID;
    @Inject("java:$conf.get('weixin.payment.secret')")
    protected String WEIXIN_PAYMENT_SECRET;
    @Inject("java:$conf.get('weixin.payment.notifyUrl')")
    protected String WEIXIN_PAYMENT_NOTIFYURL;
    @Inject("java:$conf.get('sp.channel')")
    protected String SP_CHANNEL;
    @Inject("java:$conf.get('weixin.miniapp.deposit.paid.success.notify.template')")
    protected String WEIXIN_MINIAPP_DEPOSIT_PAID_SUCCESS_NOTIFY_TEMPLATE;

    /**
     * 小程序调起支付API
     *
     * @param req
     * @return
     */
    @POST
    @Ok("json")
    @At("/requestPayment")
    @AdaptBy(type = JsonAdaptor.class)
    public BaseResp requestPayment(RequestPaymentReq req) {
        try {
            if (Lang.isEmpty(req.getAmount()) || req.getAmount() < 0) {
                return Code.resp("USER_AMOUNT_ERROR");
            } else {
                Account account = dao.fetch(Account.class, Cnd.where("userId", "=", req.getUserId()).and("source", "=", "MINIAPP"));
                Current current = new Current();
                current.setReason("保证金充值");
                current.setCurrentNum(JgcUtil.generateTradeNo("FC"));
                current.setArrived(false);
                current.setUserId(req.getUserId());
                current.setEntryTime(Times.now());
                current.setCause(true);
                current.setAmount(req.getAmount());
                dao.insert(current);
                UnifiedorderReq order = new UnifiedorderReq();
                order.setAttach(current.getCurrentId() + "");
                order.setOpenid(account.getOpenId());
                order.setAppid(WEIXIN_MINIAPP_APPID);
                order.setMch_id(WEIXIN_PAYMENT_MCHID);
                order.setNotify_url(WEIXIN_PAYMENT_NOTIFYURL);
                order.setDevice_info("WEB");
                order.setNonce_str(R.UU32());
                order.setSign_type(Dict.SIGN_TYPE_MD5);
                order.setBody(SP_CHANNEL + "保证金充值");
                order.setDetail(SP_CHANNEL);
                order.setOut_trade_no(current.getCurrentNum());
                order.setFee_type(Dict.FEE_TYPE_CNY);
                order.setTotal_fee(req.getAmount());
                order.setSpbill_create_ip(Lang.getIP(Mvcs.getReq()));
                order.setTime_start(Times.format("yyyyMMddHHmmss", Times.now()));
                order.setTime_expire(Times.format("yyyyMMddHHmmss", Times.nextMinute(Times.now(), 30)));
                order.setTrade_type("JSAPI");
                order.setSign(Lang.md5(Util.buildParmas(Lang.obj2nutmap(order), new String[]{"sign"})
                        + "&key=" + WEIXIN_PAYMENT_SECRET).toUpperCase());
                UnifiedorderResp resp = PayUtil.unifiedorder(order);
                RequestPayment rp = new RequestPayment(Times.getTS(), R.UU32(), resp.getPrepay_id());
                rp.setPaySign(Util.getRequestPaymentPaySign(WEIXIN_MINIAPP_APPID, rp, WEIXIN_PAYMENT_SECRET));
                current.setExpand(new NutMap().setv("prepay_id", rp.get$package()));
                dao.update(current, "^(expand)$");
                return JgcUtil.buildSuccessResp(new NutMap().setv("timeStamp", String.valueOf(rp.getTimeStamp()))
                        .setv("nonceStr", rp.getNonceStr())
                        .setv("package", "prepay_id=" + rp.get$package())
                        .setv("signType", rp.getSignType())
                        .setv("paySign", rp.getPaySign()));
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Code.resp("SYS_ERROR");
        }
    }

    /**
     * @param map
     * @return
     */
    @POST
    @At("/weixin/notify")
    @Ok("raw")
    @AdaptBy(type = XmlAdaptor.class)
    public String weixinNotify(NutMap map) {
        String sign = map.getString("sign");
        if (Strings.equalsIgnoreCase(map.getString("result_code"), Dict.RTN_SUCCESS)) {
            if (Strings.equalsIgnoreCase(sign, Lang.md5(Util.buildParmas(map, new String[]{"sign"}) + "&key=" + WEIXIN_PAYMENT_SECRET).toUpperCase())) {
                Current current = dao.fetch(Current.class, Cnd.where("currentNum", "=", map.getString("out_trade_no")).and("isArrived", "=", false));
                if (Lang.isEmpty(current)) {
                    return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[Order not fund]]></return_msg></xml>";
                } else {
                    current.setAmount(map.getInt("total_fee"));
                    current.setArrived(true);
                    current.setExpand(current.getExpand().setnxAll(map));
                    current.setTsn(map.getString("transaction_id"));
                    current.setArriveTime(Times.now());
                    dao.update(current, "^(amount|isArrived|expand|tsn|arriveTime)$");
//
//                    sendWxTmplMsg(current.getExpand().getString("openid"), new NutMap().setv("keyword1", new WXMsgData(margin.getMarginNum()))
//                            .setv("keyword2", new WXMsgData(margin.getAmount().toString())).setv("keyword3", new WXMsgData("保证金充值成功")),
//                            current.getExpand().getString("prepay_id"));
                    return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
                }
            } else {
                log.error("微信支付回调签名错误，" + map.toString());
                return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[Sign is error]]></return_msg></xml>";
            }
        } else {
            return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
        }
    }

    public void sendWxTmplMsg(String openId, NutMap data, String formId) {
        MessageWxopenTemplateSendReq req = new MessageWxopenTemplateSendReq();
        req.setData(data);
        req.setTouser(openId);
        req.setForm_id(formId);
        req.setAccess_token(com.jigoucai.util.Util.getToken(WEIXIN_MINIAPP_APPID, WEIXIN_MINIAPP_APPSECRET));
        req.setTemplate_id(WEIXIN_MINIAPP_DEPOSIT_PAID_SUCCESS_NOTIFY_TEMPLATE);
        req.setPage("pages/finMargin");
        MpUtil.messageWxopenTemplateSend(req);
    }
}
